package com.example.nacos.comp;

import cn.hutool.core.collection.ListUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.example.nacos.utils.CamelToUnderscore;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class BatchClickhouseComp {
    @Autowired
    private DruidDataSource dataSource;

    public <T> String health(List<T> list, Class<T> clazz) throws IOException, SQLException, IllegalAccessException, NoSuchFieldException {
        // 下载文件到服务器 打开文件并且将文件内容转换为List<bean>
        List<List<T>> newList = ListUtil.partition(list, 2);

        // 获取表名
        TableName tableName = clazz.getAnnotation(TableName.class);
        if (tableName == null) {
            throw new RuntimeException("请添加TableName注解");
        }
        String tableNameValue = tableName.value();
        log.info("表名：{}", tableNameValue);

        Field[] fields = clazz.getDeclaredFields();
        List<String> fieldList = new ArrayList<>();

        StringBuilder sb = new StringBuilder();
        StringBuilder columns = new StringBuilder();
        StringBuilder values = new StringBuilder();

        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            field.setAccessible(true);
            Order order = field.getAnnotation(Order.class);
            if (order == null) {
                continue;
            }
            log.info("映射字段：" + field.getName() + " order值为：" + order.value());
            TableField tableField = field.getAnnotation(TableField.class);
            String fileName;
            if (tableField != null) {
                fileName = tableField.value();
            } else {
                fileName = CamelToUnderscore.camelToUnderscore(field.getName());
            }
            // 添加每一列
            columns.append(fileName);
            columns.append(",");

            // 添加？
            values.append("?");
            values.append(",");
            fieldList.add(field.getName());
        }
        columns.deleteCharAt(columns.length() - 1);
        values.deleteCharAt(values.length() - 1);
        sb.append("INSERT INTO ").append(tableNameValue).append("(");
        sb.append(columns);
        sb.append(") VALUES (").append(values).append(")");
        log.info("sql:{}", sb.toString());
        DruidPooledConnection pooledConnection=null;
        PreparedStatement pstmt = null;
        try {
             pooledConnection = dataSource.getConnection();
            log.info("clickhouse批量插入开始");
             pstmt = pooledConnection
                    .prepareStatement(sb.toString());
            // clickhouse 最多批量插入数据 447条记录
            for (List<T> list1 : newList) {
                for (T t : list1) {
                    for (int i = 0; i < fieldList.size(); i++) {
                        String fieldName = fieldList.get(i);
                        Field field = clazz.getDeclaredField(fieldName);
                        field.setAccessible(true);
                        Object value = field.get(t);
                        pstmt.setObject(i + 1, value);
                        log.info("字段名：{} 字段值：{}", fieldName, value);
                    }
                    pstmt.addBatch();
                }
                pstmt.executeBatch();
                log.info("clickhouse批量插入成功---->");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(pstmt != null){
                pstmt.close();
            }
            if(pooledConnection != null) {
                pooledConnection.close();
            }
        }

        return "ok";
    }
}
